home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Carousel
/
CAROUSEL.cdr
/
mactosh
/
hc
/
tex05_sr.sit
/
appendDeleteFiles 0.5.c
next >
Wrap
Text File
|
1988-09-04
|
7KB
|
295 lines
/* new HyperCard XFCN to append or delete files
* copyright 1988 Mark ^Zimmermann - 880901-0904
* part of the TEX HyperCard package as an additional tool for
* dataspace creation and navigation...
*
* Call this XFCN as "appendDeleteFiles (cmd)". If cmd begins with the
* letter 'A', then a standard files dialog will offer a list of TEXT
* files; if one is selected, then the offer will be repeated and
* subsequent selections will be appended to the end of the first
* one. If cmd begins with the letter 'D', then files selected from
* the std files dialog (which shows all files now, now just TEXT files)
* will be irreversably (probably? barring low-level magic) deleted.
*
* Error checking is minimal, and the usual response to an error is
* to quit with some short message and a beep....
*/
#include <MacTypes.h>
#include <FileMgr.h>
#include <StdFilePkg.h>
#include <HyperXCmd.h>
#define NULL 0
/* define these to allow use of global variables in my XFCNs; a
* Lightspeed C necessity, apparently...
*/
#define SetUpA4() asm { move.l a4,-(sp) \
move.l a0,a4 }
#define RestoreA4() asm { move.l (sp)+,a4 }
pascal void main (XCmdBlockPtr paramPtr);
void doAppend (XCmdBlockPtr paramPtr);
void doDelete (XCmdBlockPtr paramPtr);
int appendNextFile (int baseFileRefNum, Str255 *nextFileName,
int nextVolRefNum, char *bufp, long myBufSize, XCmdBlockPtr paramPtr);
int adzGetFile (Str255 *fileNamePtr, int *volRefNumPtr, int numTypes);
void returnErrorMsg (XCmdBlockPtr paramPtr, char *msg);
char *strcpy (char *s1, char *s2);
int strlen (char *s);
pascal void main (paramPtr)
XCmdBlockPtr paramPtr;
{
SetUpA4();
switch (**(paramPtr->params[0]))
{
case 'A':
doAppend (paramPtr);
break;
case 'D':
doDelete (paramPtr);
break;
default:
returnErrorMsg (paramPtr,
"{Sorry, unrecognized command in appendDeleteFiles call!}");
break;
}
RestoreA4();
return;
}
/* function to do the work of appending files to the end of the
* first-chosen one... determine buffer size automatically
*/
void doAppend (paramPtr)
XCmdBlockPtr paramPtr;
{
Str255 basefileName, nextFileName;
int baseVolRefNum, baseFileRefNum, nextVolRefNum, nextFileRefNum;
long myBufSize, grow;
char *bufp;
if (adzGetFile (&basefileName, &baseVolRefNum,1))
{
if (FSOpen (basefileName, baseVolRefNum, &baseFileRefNum) != noErr)
{
returnErrorMsg (paramPtr,
"{Sorry, error while trying to open the base file!}");
return;
}
/* see how much memory we can get for our buffer here */
MaxApplZone();
myBufSize = MaxMem (&grow) - 32768; /* keep 32kB in reserve */
if ((bufp = NewPtr (myBufSize)) == NULL)
{
returnErrorMsg (paramPtr,
"{Sorry, memory manager error while getting buffer space!}");
return;
}
while (adzGetFile (&nextFileName, &nextVolRefNum, 1) &&
appendNextFile (baseFileRefNum, &nextFileName, nextVolRefNum,
bufp, myBufSize, paramPtr))
;
DisposPtr (bufp);
FSClose (baseFileRefNum);
}
return;
}
/* function to do the work of deleting files as they are chosen ... no
* particular error checking, just try to do it until 'Cancel' ... beep
* and return a polite message if unable to comply for some reason....
*/
void doDelete (paramPtr)
XCmdBlockPtr paramPtr;
{
Str255 fileName;
int volRefNum;
while (adzGetFile (&fileName, &volRefNum, -1))
if (FSDelete (fileName, volRefNum) != noErr)
{
returnErrorMsg (paramPtr,
"{Sorry, file system error while trying to delete a file!}");
break;
}
return;
}
/* routine to append the contents of nextFile X to baseFile ... does some
* limited error checking and tries to get a polite msg back to user if
* there is a problem ... returns 1 if all is well, 0 on error....
*/
int appendNextFile (baseFileRefNum, nextFileName, nextVolRefNum,
bufp, myBufSize, paramPtr)
int baseFileRefNum, nextVolRefNum;
Str255 *nextFileName;
char *bufp;
long myBufSize;
XCmdBlockPtr paramPtr;
{
int nextFileRefNum, errNum;
long count;
errNum = FSOpen (nextFileName, nextVolRefNum, &nextFileRefNum);
if (errNum != noErr && errNum != opWrErr) /* ok if read-only here */
{
returnErrorMsg (paramPtr,
"{Sorry, error while attempting to open file to be appended!}");
return (0);
}
if (SetFPos (nextFileRefNum, fsFromStart, 0L) != noErr)
{
returnErrorMsg (paramPtr,
"{Sorry, error setting pointer in file to be appended!}");
FSClose (nextFileRefNum);
return (0);
}
if (SetFPos (baseFileRefNum, fsFromLEOF, 0L) != noErr)
{
returnErrorMsg (paramPtr,
"{Sorry, error setting pointer to end of base file!}");
FSClose (nextFileRefNum);
return (0);
}
for (;;)
{
count = myBufSize;
errNum = FSRead (nextFileRefNum, &count, bufp);
if (errNum != noErr && errNum != eofErr)
{
returnErrorMsg (paramPtr,
"{Sorry, error while reading from file to be appended!}");
FSClose (nextFileRefNum);
return (0);
}
if (count == 0)
break;
if (FSWrite (baseFileRefNum, &count, bufp) != noErr)
{
returnErrorMsg (paramPtr,
"{Sorry, error while writing to base file!}");
FSClose (nextFileRefNum);
return (0);
}
}
FSClose (nextFileRefNum);
return (1); /* success, at last! */
}
/* this routine gets the name of the file to be appended or deleted ...
* pass it numTypes = 1 for restricting the Std Files Dialog view
* to type 'TEXT' only, or pass numTypes = -1 to show all files.
* The function returns 1 if a file was selected (and copies the file
* name into the place pointed to by fileNamePtr and the volume number
* into the place pointed to by volRefNumPtr), and returns 0 if the
* user chooses 'Cancel'....
*/
int adzGetFile (fileNamePtr, volRefNumPtr, numTypes)
Str255 *fileNamePtr;
int *volRefNumPtr;
int numTypes;
{
SFTypeList myFileTypes;
Point SFGwhere;
SFReply myReply;
register int i;
SFGwhere.v = 90;
SFGwhere.h = 82;
myFileTypes[0] = 'TEXT';
SFGetFile (SFGwhere, "\p", 0L, numTypes, myFileTypes, 0L, &myReply);
if (myReply.good)
{
for (i = *myReply.fName; i >= 0; --i)
(*fileNamePtr)[i] = myReply.fName[i];
*volRefNumPtr = myReply.vRefNum;
return (1);
}
else
return (0);
}
/* function to set the return value of the XFCN to a chosen error msg;
* if there isn't enough free memory to give us a Handle to the msg,
* beep a bunch and then return!
*/
void returnErrorMsg (paramPtr, msg)
XCmdBlockPtr paramPtr;
char *msg;
{
Handle answer;
int msgLength;
SysBeep (10);
msgLength = strlen (msg);
if ((answer = NewHandle (1 + msgLength)) == NULL)
{
SysBeep (10);
SysBeep (10);
SysBeep (10);
SysBeep (10);
SysBeep (10);
return;
}
strcpy (*answer, msg);
paramPtr->returnValue = answer;
return;
}
/* function to determine the length of a string ... standard thing,
* adapted from the LSC library, and K&R p.98 ....
*/
int strlen (s)
register char *s;
{
char *s0 = s;
while (*s++)
;
return (s - s0 - 1);
}
/* function to copy a string from one place to another, in a rather
* obvious fashion ... adapted from the LSC library, and K&R p.101 ....
*/
char *strcpy (s1, s2)
register char *s1, *s2;
{
char *s = s1;
while (*s1++ = *s2++)
;
return (s);
}